/**
 * 报表设计公司(2011)
 */
package com.reportgear.report.view.grid.util;

import java.awt.BasicStroke;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.Hashtable;
import java.util.Iterator;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.swing.JLabel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.reportgear.report.print.ReportPage;

/**
 * 图形帮助类
 * 
 * @version 1.0 2011-3-14
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ANNCSR 2.0
 * 
 */
public class GraphHelper {
	private static final Logger logger = LoggerFactory.getLogger(GraphHelper.class.getName());
	private static Hashtable fontMetricsHash = new Hashtable();
	// 笔触类型
	private static Stroke[] LineStrokeArray = new Stroke[15];
	private static Font oldFont = null;
	private static FontMetrics oldFontMetrics = null;
	// 临时图形对象
	private static Line2D tmpLine2D = new Line2D.Double(0.0D, 0.0D, 0.0D, 0.0D);
	// TODO 使用ImageIO
	private static final MediaTracker mediaTracker = new MediaTracker(new JLabel());

	/**
	 * 绘制形状
	 * 
	 * @param g
	 *            图形对象
	 * @param shape
	 *            待绘制的形状
	 */
	public static void draw(Graphics2D g, Shape shape) {
		draw(g, shape, 1);
	}

	/**
	 * 绘制形状
	 * 
	 * @param g2
	 *            图形对象
	 * @param shape
	 *            待绘制的形状
	 * @param stroke
	 *            笔划类型
	 */
	public static void draw(Graphics2D g2, Shape shape, int stroke) {
		GraphHelper.setStoke(g2, GraphHelper.getStroke(stroke));
		g2.draw(shape);
	}

	/**
	 * 绘制线条
	 * 
	 * @param g2
	 *            图形对象
	 * @param x1
	 *            起点x
	 * @param y1
	 *            起点y
	 * @param x2
	 *            终点x
	 * @param y2
	 *            终点y
	 */
	public static void drawLine(Graphics2D g2, double x1, double y1, double x2, double y2) {
		GraphHelper.drawLine(g2, x1, y1, x2, y2, 1);
	}

	/**
	 * 绘制线条
	 * 
	 * @param g2
	 *            图形对象
	 * @param x1
	 *            起点x
	 * @param y1
	 *            起点y
	 * @param x2
	 *            终点x
	 * @param y2
	 *            终点y
	 * @param stroke
	 *            笔划类型
	 */
	public static void drawLine(Graphics2D g2, double x1, double y1, double x2, double y2, int stroke) {
		GraphHelper.tmpLine2D.setLine(x1, y1, x2, y2);
		GraphHelper.draw(g2, GraphHelper.tmpLine2D, stroke);
	}

	/**
	 * 绘制矩形
	 * 
	 * @param g
	 *            图形对象
	 * @param x1
	 *            矩形第一点x
	 * @param y1
	 *            矩形第一点y
	 * @param x2
	 *            矩形第二点x
	 * @param y2
	 *            矩形第二点y
	 */
	public static void drawRect(Graphics2D g2, double x1, double y1, double x2, double y2) {
		drawRect(g2, x1, y1, x2, y2, 1);
	}

	/**
	 * 绘制矩形
	 * 
	 * @param g
	 *            图形对象
	 * @param x1
	 *            矩形第一点x
	 * @param y1
	 *            矩形第一点y
	 * @param x2
	 *            矩形第二点x
	 * @param y2
	 *            矩形第二点y
	 * @param stroke
	 *            笔划类型
	 */
	public static void drawRect(Graphics2D g2, double x1, double y1, double x2, double y2, int stroke) {
		draw(g2, new Rectangle2D.Double(x1, y1, x2, y2), stroke);
	}

	/**
	 * 绘制普通文字
	 * 
	 * @param g
	 *            图形对象
	 * @param str
	 *            字符串
	 * @param x
	 *            起点x
	 * @param y
	 *            起点y
	 */
	private static void drawNormalString(Graphics g, String str, double x, double y) {
		final Graphics2D g2 = (Graphics2D) g;
		g2.drawString(str, (float) x, (float) y);
	}

	/**
	 * 绘制字符串
	 * 
	 * @param g
	 *            图形对象
	 * @param str
	 *            字符串
	 * @param x
	 *            起点x
	 * @param y
	 *            起点y
	 */
	public static void drawString(Graphics g, String str, double x, double y) {
		if ((str == null) || (str.length() == 0)) {
			return;
		}
		// if (g.getFont() instanceof ReportFont) {
		// ReportFont frFont = (ReportFont) g.getFont();
		// FontMetrics fontMetrics = g.getFontMetrics(frFont);
		// int i = frFont.getStyle();
		// if (frFont.isSuperscript()) {
		// y -= fontMetrics.getAscent() / 3;
		// frFont = ReportFont.getInstance(frFont.getName(), i, frFont.getSize()
		// * 2 / 3, frFont.getForeground(),
		// frFont.getUnderline(), frFont.isStrikethrough(), frFont.isShadow(),
		// frFont.isSuperscript(),
		// frFont.isSubscript());
		// fontMetrics = g.getFontMetrics(frFont);
		// g.setFont(frFont);
		// } else if (frFont.isSubscript()) {
		// // y += fontMetrics.getDescent() / 3;
		// // frFont = ReportFont.getInstance(frFont.getName(), i,
		// frFont.getSize() * 2 / 3, frFont.getForeground(),
		// // frFont.getUnderline(), frFont.isStrikethrough(),
		// frFont.isShadow(), frFont.isSuperscript(),
		// // frFont.isSubscript());
		// // fontMetrics = g.getFontMetrics(frFont);
		// // g.setFont(frFont);
		// }
		// if (frFont.isShadow()) {
		// Color localColor = g.getColor();
		// g.setColor(localColor.brighter());
		// drawNormalString(g, str, x + 1.0D, y + 1.0D);
		// g.setColor(localColor);
		// }
		// drawNormalString(g, str, x, y);
		// if (frFont.getUnderline() != 0) {
		// double tmpY1 = y + fontMetrics.getDescent() +
		// getLineStyleSize(frFont.getUnderline());
		// drawLine(g, x, tmpY1, x + fontMetrics.stringWidth(str), tmpY1,
		// frFont.getUnderline());
		// }
		// if (!(frFont.isStrikethrough())) {
		// return;
		// }
		//
		// double tmpY2 = y - fontMetrics.getAscent() + (fontMetrics.getHeight()
		// + 1) / 2;
		// drawLine(g, x, tmpY2, x + fontMetrics.stringWidth(str), tmpY2, 1);
		// } else {
		GraphHelper.drawNormalString(g, str, x, y);
		// }
	}

	/**
	 * 填充形状
	 * 
	 * @param g
	 *            图形背景
	 * @param shape
	 *            形状
	 */
	public static void fill(Graphics2D g2, Shape shape) {
		g2.fill(shape);
	}

	/**
	 * 填充矩形
	 * 
	 * @param g
	 *            图形对象
	 * @param x1
	 *            矩形第一点x
	 * @param y1
	 *            矩形第一点y
	 * @param x2
	 *            矩形第二点x
	 * @param y2
	 *            矩形第二点y
	 */
	public static void fillRect(Graphics2D g2, double x1, double y1, double x2, double y2) {
		fill(g2, new Rectangle2D.Double(x1, y1, x2, y2));
	}

	/**
	 * 字体度量值
	 * 
	 * @param font
	 * @return
	 */
	public static FontMetrics getFontMetrics(Font font) {
		if (font == GraphHelper.oldFont) {
			return GraphHelper.oldFontMetrics;
		}
		// if (paramFont == null) {
		// localObject = FRContext.getDefaultValues();
		// paramFont = ((DefaultValues) localObject).getFRFont();
		// }

		Object localFont = GraphHelper.fontMetricsHash.get(font);
		if (localFont == null) {
			localFont = Toolkit.getDefaultToolkit().getFontMetrics(font);
			GraphHelper.fontMetricsHash.put(font, localFont);
		}
		GraphHelper.oldFont = font;
		GraphHelper.oldFontMetrics = (FontMetrics) localFont;
		return ((FontMetrics) localFont);
	}

	public static int getLineStyleSize(int paramInt) {
		if (paramInt == 0) {
			return 0;
		}
		if ((paramInt == 2) || (paramInt == 6) || (paramInt == 8) || (paramInt == 10) || (paramInt == 12)
				|| (paramInt == 13)) {
			return 2;
		}
		if (paramInt == 5) {
			return 3;
		}

		return 1;
	}

	/**
	 * 获取笔划
	 * 
	 * @param stroke
	 *            笔划类型
	 * @return 笔划对象
	 */
	public static Stroke getStroke(int stroke) {
		Stroke retStroke = null;
		if (stroke < GraphHelper.LineStrokeArray.length) {
			retStroke = GraphHelper.LineStrokeArray[stroke];
			if (retStroke != null) {
				return retStroke;
			}
		}
		final Stroke[] arrayOfStroke = GraphHelper.LineStrokeArray;
		GraphHelper.LineStrokeArray = new Stroke[Math.max(10, arrayOfStroke.length * 2)];
		System.arraycopy(arrayOfStroke, 0, GraphHelper.LineStrokeArray, 0, arrayOfStroke.length);

		final int i = 0;
		final int j = 0;
		switch (stroke) {
		case 1:
			retStroke = new BasicStroke(1.0F, i, j);
			break;
		case 2:
			retStroke = new BasicStroke(2.0F, i, j);
			break;
		case 3:
			retStroke = new BasicStroke(1.0F, i, j, 10.0F, new float[] { 4.0F, 2.0F }, 0.0F);
			break;
		case 4:
			retStroke = new BasicStroke(1.0F, i, j, 10.0F, new float[] { 2.0F }, 0.0F);
			break;
		case 14:
			retStroke = new BasicStroke(1.0F, i, j, 10.0F, new float[] { 4.0F }, 0.0F);
			break;
		case 5:
			retStroke = new BasicStroke(3.0F, i, j);
			break;
		case 6:
			break;
		case 7:
			retStroke = new BasicStroke(1.0F, i, j, 10.0F, new float[] { 1.0F }, 0.0F);
			break;
		case 8:
			retStroke = new BasicStroke(2.0F, i, j, 10.0F, new float[] { 8.0F, 2.0F }, 0.0F);
			break;
		case 9:
			retStroke = new BasicStroke(1.0F, i, j, 10.0F, new float[] { 8.0F, 4.0F, 2.0F, 4.0F }, 0.0F);
			break;
		case 10:
			retStroke = new BasicStroke(2.0F, i, j, 10.0F, new float[] { 8.0F, 4.0F, 2.0F, 4.0F }, 0.0F);
			break;
		case 11:
			retStroke = new BasicStroke(1.0F, i, j, 10.0F, new float[] { 8.0F, 4.0F, 2.0F, 4.0F, 2.0F, 4.0F }, 0.0F);
			break;
		case 12:
			retStroke = new BasicStroke(2.0F, i, j, 10.0F, new float[] { 8.0F, 4.0F, 2.0F, 4.0F, 2.0F, 4.0F }, 0.0F);
			break;
		case 13:
			retStroke = new BasicStroke(2.0F, i, j, 10.0F, new float[] { 8.0F, 4.0F, 2.0F, 4.0F }, 0.0F);
		case 15:
		}
		if (retStroke == null) {
			retStroke = new BasicStroke(1.0F, i, j);
		}

		GraphHelper.LineStrokeArray[stroke] = retStroke;
		return retStroke;
	}

	/**
	 * 获取笔划
	 * 
	 * @param g2
	 *            图形对象
	 * @param stroke
	 *            笔划
	 */
	public static void setStoke(Graphics2D g2, Stroke stroke) {
		final Stroke oldStroke = g2.getStroke();
		if (stroke.equals(oldStroke)) {
			return;
		}
		g2.setStroke(stroke);
	}

	public static BufferedImage createBufferedImageFromImage(Image image) {
		if (image instanceof BufferedImage) {
			return ((BufferedImage) image);
		}
		waitForImage(image);
		int w = image.getWidth(null);
		int h = image.getHeight(null);
		BufferedImage bufferImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = bufferImage.createGraphics();
		g2.drawImage(image, 0, 0, null);

		return bufferImage;
	}

	public static void waitForImage(Image image) {
		mediaTracker.addImage(image, 0);
		try {
			mediaTracker.waitForAll();
		} catch (Exception localException) {
		}
		mediaTracker.removeImage(image);
	}
}
